﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using iTextSharp.text;

namespace Vcm
{
    public static class ImageProvider
    {
        private static readonly Dictionary<string, Image> _images = new Dictionary<string, Image>();

        /// <summary>
        /// Gets an image and resize it by keeping its proportion so it fits within a given maximum size. 
        /// If a non-empty key is provided, the image is stored in a dictionary and will be reused, in order to reduce the pdf size.
        /// </summary>
        /// <param name="key">The key of the image.</param>
        /// <param name="path">The path of the image file.</param>
        /// <param name="imageExtensions">The available image extensions (not preceeded by a '.').</param>
        /// <param name="maxWidth">The maximum width of the resized image.</param>
        /// <param name="maxHeight">The maximum height of the resized image.</param>
        /// <returns>The image resized.</returns>
        public static Image GetFittingImage(string key, string path, string[] imageExtensions, float maxWidth, float maxHeight)
        {
            return GetSizedImage(key, path, imageExtensions, maxWidth, maxHeight,
                image => image.ScaleToFit(maxWidth, maxHeight));
        }

        public static Image GetFittingImage(string key, string path, float maxWidth, float maxHeight)
        {
            return GetSizedImage(key, path, null, maxWidth, maxHeight,
                image => image.ScaleToFit(maxWidth, maxHeight));
        }

        /// <summary>
        /// Gets an image and resize it to an absolute size. If a non-empty key is provided, the image
        /// is stored in a dictionary and will be reused, in order to reduce the pdf size.
        /// </summary>
        /// <param name="key">The key of the image.</param>
        /// <param name="path">The path of the image file.</param>
        /// <param name="imageExtensions">The available image extensions (not preceeded by a '.').</param>
        /// <param name="absoluteWidth">The absolute width of the resized image.</param>
        /// <param name="absoluteHeight">The absolute height of the resized image.</param>
        /// <returns>The image resized.</returns>
        public static Image GetAbsoluteSizedImage(string key, string path, string[] imageExtensions, float absoluteWidth, float absoluteHeight)
        {
            return GetSizedImage(key, path, imageExtensions, absoluteWidth, absoluteWidth, 
                image => image.ScaleAbsolute(absoluteWidth, absoluteHeight));
        }

        //public static Image GetAbsoluteSizedImage2(string key, string path, string[] imageExtensions, float absoluteWidth, float absoluteHeight)
        //{
        //    return GetSizedImage(key, path, imageExtensions, absoluteWidth, absoluteWidth,
        //        image => image.ScaleToFit(absoluteWidth, absoluteHeight));
        //}

        public static Image GetAbsoluteSizedImage(string key, string path, float absoluteWidth, float absoluteHeight)
        {
            return GetSizedImage(key, path, null, absoluteWidth, absoluteWidth,
                image => image.ScaleAbsolute(absoluteWidth, absoluteHeight));
        }

        public static Image GetSizedImage(string key, string path, IEnumerable<string> imageExtensions, float width, float height, Action<Image> resizeAction)
        {
            var fullKey = key + width + "x" + height;
            Image result;
            if (String.IsNullOrEmpty(key) || !_images.TryGetValue(fullKey, out result))
            {
                var fullpath = imageExtensions != null
                    ? SearchImage(path, imageExtensions)
                    : path;
                if (fullpath == null)
                {
                    if(!String.IsNullOrEmpty(key))
                        _images.Add(fullKey, null);
                    return null;
                }
                result = Image.GetInstance(fullpath);
                resizeAction(result);
                if (!String.IsNullOrEmpty(key))
                    _images.Add(fullKey, result);
            }
            return result;
        }

        private static string SearchImage(string path, IEnumerable<string> imageExtensions)
        {
            return imageExtensions
                .Select(imageExtension => path + "." + imageExtension)
                .FirstOrDefault(File.Exists);
        }
    }
}